'use strict';

const Controller = require('egg').Controller;
const fs = require('fs');
const path = require('path');
const FILE_PATH = path.resolve(__dirname, '../../files');
class HomeController extends Controller {
  async index() {
    const { ctx } = this;
    ctx.body = 'hi, egg';
  }
  async upload() {
    const { ctx } = this;
    const [ chunk ] = await ctx.request.files; // 获取切片
    if (chunk) {
      // 处理文件
      try {
        const hashName = chunk.filename.split('-')[0];
        const fileHashDir = path.resolve(FILE_PATH, hashName);
        if (!fs.existsSync(fileHashDir)) {
          fs.mkdirSync(fileHashDir);
        }
        const name = path.resolve(FILE_PATH, fileHashDir, path.basename(chunk.filename));
        await fs.promises.copyFile(chunk.filepath, name);
      } finally {
        await fs.promises.unlink(chunk.filepath);
      }
    }
    ctx.body = {
      code: 10000,
      data: {
        uploaded: true,
      },
      message: '上传成功',
    };

  }

  // 检查文件是否
  async checkFileUpload() {
    const { ctx } = this;
    try {
      const { hash } = ctx.request.body;
      if (hash) {
        const files = await fs.promises.readdir(FILE_PATH);
        const FileName = files.find(item => item.split('.')[0] === hash);
        if (FileName) {
          // 上传过或者上传过切片
          // 检查是文件还是切片- 文件就是完整上传过 切片就是目录
          const filePath = path.resolve(FILE_PATH, FileName);
          const isDirectory = await (await fs.promises.stat(filePath)).isDirectory();
          if (isDirectory) {
            const chunkList = await fs.promises.readdir(filePath); // 分片数量
            let max = 0;
            chunkList.forEach(item => {
              const current = item.substring(item.lastIndexOf('-') + 1, item.lastIndexOf('.'));
              if (max < +current) {
                max = (+current);
              }
            });
            // 是文件夹说明之前上传的分片没有合成
            ctx.body = { code: 0, message: '切片存在', data: {
              uploaded: false,
              lastSlice: max, // 没有上传的切片
            } };
          } else {
            ctx.body = { code: 0, message: '秒传成功', data: {
              uploaded: true,
              url: `/files/${FileName}`,
            } };
          }
        } else {
          ctx.body = { code: 0, message: '没有上传过', data: {
            uploaded: false,
          } };
        }
      } else {
        ctx.body = { code: 0, message: '没有上传过', data: {
          uploaded: false,
        } };
      }
    } catch (error) {
      console.log(error);
      ctx.response.status = 500;
      ctx.body = { code: 1, message: '处理异常' + error.message };
    }

  }
  // 合并文件
  async mergeFile() {
    // 合并文件
    const { ctx } = this;
    const { hash, ext } = ctx.request.body;
    if (hash) {
      const chunkPath = path.resolve(FILE_PATH, hash);
      const chunkList = await fs.promises.readdir(chunkPath);
      let len = 0;
      const list = chunkList.map(item => {
        const buffer = fs.readFileSync(chunkPath + '/' + item);
        len += buffer.length;
        return buffer;
      });
      const buffer = Buffer.concat(list, len);
      const ws = fs.createWriteStream(chunkPath + '.' + ext);
      ws.write(buffer);
      ws.close();
      await this.removeDir(chunkPath); // 删除分片
      ctx.body = {
        code: 0,
        message: '合并文件成功',
        data: {
          chunkList,
        },
      };
    } else {
      ctx.body = {
        code: 1,
        message: '没有传hash值',
      };
    }
  }
  async removeDir(p) {
    const statObj = fs.statSync(p); // fs.statSync同步读取文件状态，判断是文件目录还是文件。
    if (statObj.isDirectory()) { // 如果是目录
      let dirs = fs.readdirSync(p); // fs.readdirSync()同步的读取目标下的文件 返回一个不包括 '.' 和 '..' 的文件名的数组['b','a']
      dirs = dirs.map(dir => path.join(p, dir)); // 拼上完整的路径
      for (let i = 0; i < dirs.length; i++) {
        // 深度 先将儿子移除掉 再删除掉自己
        this.removeDir(dirs[i]);
      }
      fs.rmdirSync(p); // 删除目录
    } else {
      fs.unlinkSync(p); // 删除文件
    }
  }
}

module.exports = HomeController;
